package meow

import grails.converters.JSON

class StatusController {

  // the delete, save and update actions only accept POST requests
  static allowedMethods = [delete: 'POST', update: 'POST']

  def authenticateService
  def twitterService

  /** タイムラインをみる  */
  def timeline = {
    // UrlMappingsとSecurityConfigだけでは設定できないので，
    // 明示的にログインの有無をチェックしている。
    if (authenticateService.isLoggedIn()) {
      twitterService.findTimelines(0, principalInfo.username)
    }
    else {
      // 未ログインで，url:/ にアクセスした輩をログイン画面に飛ばす
      redirect(controller: 'login', action: 'auth')
    }
  }

  /** つぶやきをみる   */
  def list = {
    def user = Account.findByUsername(params.username)
    if (!user) {
      // 指定したユーザが居なければ 404 を返す
      response.sendError(404)
      return
    }
    def messages = twitterService.findStatuses(0, params.username).statuses
    def feed = {
      title = "Twitter Clone Status Messages"
      // BUGS: なぜかコンテキストパスが展開されないので苦肉の策を弄してみたよ
      link = g.createLink(controller: params.username, absolute: true)
          .replaceAll(/\/${params.username}/, "${request.contextPath}/${params.username}")
      description = ""

      for (msg in messages) {
        entry("${msg.account.userRealName} said:") {
          // BUGS: なぜかコンテキストパスが展開されないので苦肉の策を弄してみたよ
          link = g.createLink(controller: params.username, action: "status", id:msg.id, absolute: true)
              .replaceAll(/\/${params.username}/, "${request.contextPath}/${params.username}")
          publishedDate = msg.dateCreated
          msg.message
        }
      }
    }
    withFormat {
      html {
        render(view: "status",
            model: twitterService.findStatuses(0, params.username))
      }
      rss { render(feedType:"rss", feed) }
      atom { render(feedType:"atom", feed) }
    }
  }

  /** パブリックタイムラインをみる */
  def publicTimeline = {
    // MEMO:超やっつけ仕事でゴメン。
    render(view: "public_timeline",
          model:[statusList: Status.list(max:20, sort:"dateCreated", order:"desc")])
  }

  /** リプライをみる  */
  def replies = {
    twitterService.findReplies(0, principalInfo.username)
  }

  /** フォローしている？  */
  def isFollowed = {
    if (params.username == principalInfo.username) {
      render text: "それはあなたです"
    }
    else {
      def follower = Followers.withCriteria {
        owner { eq 'username', principalInfo.username }
        target { eq 'username', params.username }
      }
      render template: (follower ? "ajax_unfollow_form"
                        : "ajax_follow_form"),
          model: [username: params.username]
    }
  }

  /** フォローする   */
  def follow = {
    twitterService.follow(principalInfo.username, params.id)
    render template: "ajax_unfollow_form", model: [username: params.id]
  }
  /** フォローをやめる   */
  def unfollow = {
    twitterService.unfollow(principalInfo.username, params.id)
    render template: "ajax_follow_form", model: [username: params.id]
  }

  /** タイムラインをページングする(AJAX)  */
  def ajaxTimeline = {
    render(template: "ajax_timeline",
        model: twitterService.findTimelines(params.page.toInteger(),
            principalInfo.username)) // <- タイムラインはログインした人だけ
  }

  /** つぶやきをページングする(AJAX)  */
  def ajaxStatus = {
    render(template: "ajax_status",
        model: twitterService.findStatuses(params.page.toInteger(), params.username))
  }

  /** リプライをページングする(AJAX)  */
  def ajaxReplies = {
    render(template: "ajax_replies",
        model: twitterService.findReplies(params.page.toInteger(),
            principalInfo.username))   // <- リプライもログインした人だけ
  }

  /** 個別のつぶやきをみる  */
  def show = {
    def status = Status.get(params.id)
    if (!status) {
      // ステータスが存在しない場合は，404とする
      response.sendError(404)
    }
    else if (params.username != status.account.username) {
      // ユーザIDと一致しなければ 404 とする
      response.sendError(404)
    }
    else {
      [status: status]
    }
  }

  /** つぶやく  */
  def update = {
    // 投稿するとタイムライン画面をすべて書き換え直すのでページングがリセットされる。
    // → 制限事項だ，ゆるせ。
    def status = new Status()
    status.account = Account.findByUsername(principalInfo.username)
    // メッセージの正規化
    status.message = params.message.replaceAll("[\t\n]", " ").trim()
    // 空メッセージはエラーではなくスルーするので，これ(↓)で良い
    if (status.validate() && status.message != "") {
      // つぶやきを登録
      twitterService.updateStatus(status)
      // MEMO: AJAXの戻りにFlashメッセージを使うのはよろしくないみたいだ（１回でflashしないで残る）。
      flash.message = status.message
      // ためしにJSON形式で返してみた。ポイントは，g.render()だよ。
      render([main: g.render(template: 'ajax_update',
                             model: twitterService.findTimelines(0, principalInfo.username)),
              count: Status.totalCount(principalInfo.username)] as JSON)
    }
    else {
      // 何もしないで，エコーバックする
      // ためしにJSON形式で返してみた。
      render([main: g.render(template: "ajax_update",
                             model: [status: status] + twitterService.findTimelines(0, principalInfo.username)),
              count: Status.totalCount(principalInfo.username)] as JSON)
    }
  }

  /** つぶやきを削除する  */
  def delete = {
    def status = Status.get(params.id)
    if (status) {
      if (status.account.username != principalInfo.username) {
        flash.message = "このつぶやきは，あなたのものではありません"
      }
      else {
        Timeline.executeUpdate("delete Timeline t where t.status.id = ?", [status.id])
        Reply.executeUpdate("delete Reply r where r.status.id = ?", [status.id])
        status.delete()
        flash.message = "Status ${status.id} deleted."
      }
      redirect action: timeline
    }
  }

}
